<?php

namespace app\api\http;

use GatewayWorker\Lib\Gateway;
use think\facade\Db;
use app\common\util\JwtUtil;
use Exception;

/**
 * Worker 命令行服务类 php think worker:gateway  -d/stop 守护/停止
 */
class Events
{
  /**
   * onConnect 事件回调
   * 当客户端连接上gateway进程时(TCP三次握手完毕时)触发
   * @param  int $client_id
   * @return void
   */
  public static function onConnect($client_id)
  {
    try {
      $res = [
        'type' => 'connect',
        'client_id' => $client_id
      ];
      Gateway::sendToCurrentClient(json_encode($res, true));
    } catch (Exception $e) {
      trace('onConnect时出错:' . json_encode($e), 'GatewayWorker');
    }
  }

  /**
   * onMessage 事件回调
   * 当客户端发来数据(Gateway进程收到数据)后触发
   * 注意：能操作数据库，尽量不要去调用模型，只用到thinkphp 的 Db
   * @param  int $client_id
   * @param  mixed $data
   * @return void
   */
  public static function onMessage($client_id, $data)
  {
    $form = json_decode($data, true);
    if (isset($form['type']) && !empty($form['type'])) {
      switch ($form['type']) {
        case 'ping': //轮巡消息
          $res = ['type' => 'ping', 'status' => 'keep connection.'];
          Gateway::sendToClient($client_id, json_encode($res, true));
          break;
        case 'bind': //绑定
          if (isset($form['formId'])) {
            if (isset($form['token']) && !empty($form['token'])) {
              $payload = JwtUtil::decode($form['token']);
              if (empty($payload) || empty($payload['uid']) || empty($payload['last_time'])) {
                Gateway::sendToClient($client_id, '哪凉快哪呆去！');
                return;
              }
              if ($payload['uid'] != $form['formId']) {
                Gateway::sendToClient($client_id, '大师有失身份啊！');
                return;
              }
            } else {
              Gateway::sendToClient($client_id, '您未登录');
              return;
            }
            $res = ['type' => 'bind', 'formId' => $form['formId']];
            // 将当前链接与uid绑定
            Gateway::bindUid($client_id, $form['formId']);
            Gateway::sendToClient($client_id, json_encode($res, true)); //通知当前客户端已绑定，可以初始化
            // 上线
            Db::name('sys_user')->where('id', $form['formId'])->update(['online' => 1, 'client_id' => $client_id]);
            //加入群聊--所有群
            $ret = Db::name('im_group_user')->where('uid', $form['formId'])->select();
            if ($ret) {
              foreach ($ret as $key => $vo) {
                Gateway::joinGroup($client_id, $vo['group_id']); //将登录用户加入群组
              }
            }
          }
          break;
        case 'hisnosend': //历史记录
          //聊天的离线
          if (isset($form['formId']) && !empty($form['formId'])) {
            //查询有无需要推送的离线信息
            $time = time() - 2592000; //30天内，超过不处理--防止数据表太大，爆掉
            $where = [];
            $where[] = ['rece_id', '=', $form['formId']]; // 我接收的，全部推过来
            $where[] = ['create_time', '>', $time];
            $where[] = ['is_send', '<>', 1];
            $resMsg = Db::name('im_chatlog')->where($where)->select();
            if ($resMsg) {
              $log_message = ['type' => 'logMessage', 'formId' => $form['formId'], 'list' => $resMsg];
              //批量推送
              Gateway::sendToUid($form['formId'], json_encode($log_message, true));
              //设置推送状态为已经推送
              Db::name('im_chatlog')->where($where)->update(['is_send' => 1]);
            }
          }
          break;
        case 'flowhis': //推送的离线信息
          if (isset($form['formId']) && !empty($form['formId'])) {
            $log_message = ['type' => 'flowhis', 'formId' => $form['formId'], 'list' => [], 'sysmsg' => []];
            try {
              //查询有无需要推送的离线信息
              $time = time() - 2592000; //30天内，超过不处理
              $where = [];
              $where[] = ['m.rece_id', '=', $form['formId']]; // 我接收的，全部推过来
              $where[] = ['m.create_time', '>', $time];
              $resMsg = Db::name('pmm_message')->alias('m')
                ->leftjoin('pmm_flow_bill b', 'm.m_id=b.id')
                ->field('m.*,b.put_uid,b.put_name,b.put_dept_id,b.put_dept_id_name,b.flow_brief,b.now_audit_name,b.now_audit_id')
                ->where($where)->select();
              $sysMsg = Db::name('im_message')->where([
                ['create_time', '>', $time],
                ['rece_id', '=', $form['formId']],
                ['is_send', '<>', 3],
              ])->select();

              if ($resMsg) {
                $log_message['list'] = $resMsg;
              }
              if ($sysMsg) {
                $log_message['sysmsg'] = $sysMsg;
              }
            } catch (Exception $e) {
              trace('flowhis时出错:' . json_encode($e), 'GatewayWorker');
            }
            //推送
            Gateway::sendToUid($form['formId'], json_encode($log_message, true));
          }
          break;
        case 'chat': //聊天
          if (
            isset($form['formId']) && !empty($form['formId']) &&
            isset($form['chat_type']) && !empty($form['chat_type']) &&
            isset($form['contype']) && !empty($form['contype'])
          ) {
            $send = Db::name('sys_user')->field('id,un,real_name,avatar')->where('id', $form['formId'])->where('status', 1)->find();
            if (!$send) { //不存在
              return;
            }
            $chat_type = (int)$form['chat_type'];
            if ($chat_type == 1) {
              if (isset($form['toId']) && !empty($form['toId'])) {
                if ($form['formId'] == $form['toId']) {
                  return; //不能自个发给自个
                }
                $rece = Db::name('sys_user')->field('id,un,real_name,avatar')->where('id', $form['toId'])->where('status', 1)->find();
                if (!$rece) { //不存在
                  return;
                }
              } else { //缺参
                return;
              }
            }
            if ($chat_type == 2) {
              if (isset($form['group_id']) && !empty($form['group_id'])) {
                $group = Db::name('im_group')->field('id,name,chat_head')->where('id', $form['group_id'])->where('status', 1)->find();
                if (!$group) { //不存在
                  return;
                }
              } else { //缺参
                return;
              }
              // 找出群里所有人uid
              $group_uids = Db::name('im_group_user')->where('group_id', $group['id'])->column('uid');
              if (!$group_uids) { //没人
                return;
              }
            }

            // 保存聊天记录
            $saveData = [
              'send_id' => $send['id'],
              'send_id_name' => $send['real_name'] ? $send['real_name'] : $send['un'],
              'send_id_avatar' => _img($send['avatar']),
              'rece_id' => $chat_type == 1 ? $rece['id'] : 0,
              'rece_id_name' => $chat_type == 1 ? ($rece['real_name'] ? $rece['real_name'] : $rece['un']) : '',
              'rece_id_avatar' => $chat_type == 1 ? _img($rece['avatar']) : '',
              'group_id' => $chat_type == 2 ? $group['id'] : 0,
              'group_id_name' => $chat_type == 2 ? $group['name'] : '',
              'group_id_avatar' => $chat_type == 2 ? _img($group['chat_head']) : '',
              'group_uid' =>  $chat_type == 2 ? implode(',', $group_uids) : '',
              'content_type' => $form['contype'],
              'content' => (isset($form['content']) && $form['content'] != '') ? $form['content'] : '',
              'files_url' => (isset($form['files_url']) && !empty($form['files_url'])) ? config('kaige.domain_name') . $form['files_url'] : '',
              'chat_type' => $form['chat_type'],
              'status' => 2,
              'is_send' => $chat_type == 2 ? 1 : 2,  //群聊默认已发送
              'group_status' => '' . $send['id'] . '', //自己发来的，读状态先加进去
              'create_time' => time(),
            ];

            $online = false;
            if ($chat_type == 1 && Gateway::isUidOnline($form['toId']) == 1) { //写这里，省去一次数据更新操作
              $online = true;
              $saveData['status'] = 1; // 群聊时没用到这个字段，所以不用判断$chat_type
            }

            //保存到数据库
            $log_id = Db::name('im_chatlog')->strict(false)->insertGetId($saveData);
            //拼给用户
            $saveData['id'] = $log_id;
            $saveData['type'] = 'chat';
            $saveData['time'] = $saveData['create_time'];
            //如果群聊
            if ($chat_type == 2) {
              Gateway::sendToGroup($form['group_id'], json_encode($saveData, true));
            } elseif ($chat_type == 1) { //单聊
              //如果在线，发给对方
              if ($online) {
                Gateway::sendToUid($form['toId'], json_encode($saveData, true));
              }
              //发给自已
              Gateway::sendToUid($form['formId'], json_encode($saveData, true));
            }
          }
          break;
        case 'readreceipt': //已读
          $re = '';
          if ($form['chat_type'] && $form['formId'] && $form['toId']) {
            if ($form['chat_type'] == 1) {
              $sql = 'UPDATE ' . env('database.prefix') . 'im_chatlog SET status=1 WHERE (rece_id=' . $form['formId'] . ' AND send_id=' . $form['toId'] . ') OR (send_id=' . $form['formId'] . ' AND rece_id=' . $form['toId'] . ')';
              Db::query($sql);
            } elseif ($form['chat_type'] == 2) {
              $sql = 'SELECT * FROM sz_im_chatlog WHERE group_id=' . $form['toId'] . ' AND FIND_IN_SET(' . $form['formId'] . ',group_status)=0';
              $elist = Db::query($sql);
              if ($elist) {
                foreach ($elist as $k => $v) {
                  if ($v['group_status']) {
                    Db::name('im_chatlog')->where('id', $v['id'])->where('group_id', $form['toId'])->update(['group_status' => $v['group_status'] . ',' . $form['formId']]);
                  } else {
                    Db::name('im_chatlog')->where('id', $v['id'])->where('group_id', $form['toId'])->update(['group_status' => $v['group_status'] . $form['formId']]);
                  }
                }
              }
            }
            Gateway::sendToUid($form['formId'], json_encode([
              'type' => 'readreceipt',
              'formId' => $form['formId'],
              'toId' => $form['toId'],
              'chat_type' => $form['chat_type']
            ], true));
          }
          break;
      }
    }
  }
}
